package com.xli.organ.user.frameuserrolerelation.service.impl;

import com.alicp.jetcache.Cache;
import com.alicp.jetcache.CacheManager;
import com.alicp.jetcache.anno.CacheConsts;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.template.QuickConfig;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xli.organ.user.frameuserrolerelation.entity.FrameUserRoleRelation;
import com.xli.organ.user.frameuserrolerelation.entity.UserRoleCache;
import com.xli.organ.user.frameuserrolerelation.mapper.FrameUserRoleRelationMapper;
import com.xli.organ.user.frameuserrolerelation.mapper.IUserRoleCacheMapper;
import com.xli.organ.user.frameuserrolerelation.service.IFrameUserRoleRelationService;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

@Validated
@Service
public class FrameUserRoleRelationServiceImpl extends ServiceImpl<FrameUserRoleRelationMapper, FrameUserRoleRelation> implements IFrameUserRoleRelationService {

    private final Lock lock = new ReentrantLock();

    @Autowired
    CacheManager cacheManager;

    Cache<Long, List<UserRoleCache>> userRoleCache;

    @PostConstruct
    public void init() {
        lock.lock();
        try {
            QuickConfig qc = QuickConfig.newBuilder("frame_user_role:list:")
                    .expire(Duration.ofSeconds(CacheConsts.DEFAULT_EXPIRE))
                    .cacheType(CacheType.LOCAL)
                    .syncLocal(true)
                    .build();
            userRoleCache = cacheManager.getOrCreateCache(qc);

            List<FrameUserRoleRelation> relationList = this.findList(new QueryWrapper<>());
            List<UserRoleCache> cacheList = IUserRoleCacheMapper.INSTANCE.toCacheList(relationList);

            Map<Long, List<UserRoleCache>> groupList = cacheList.stream()
                    .collect(Collectors.groupingBy(UserRoleCache::getUser_id));
            groupList.forEach((userId, roleList) -> userRoleCache.put(userId, roleList));
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean insert(FrameUserRoleRelation frameUserRoleRelation) {
        lock.lock();
        try {
            boolean result = this.save(frameUserRoleRelation);
            if (result) {
                List<UserRoleCache> cacheList = userRoleCache.get(generateKey(frameUserRoleRelation));
                if (cacheList == null) {
                    cacheList = new ArrayList<>();
                }
                cacheList.add(IUserRoleCacheMapper.INSTANCE.toCacheEntity(frameUserRoleRelation));
                userRoleCache.put(generateKey(frameUserRoleRelation), cacheList);
            }
            return result;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean delete(Long id) {
        lock.lock();
        try {
            FrameUserRoleRelation frameUserRoleRelation = this.find(id);
            if (frameUserRoleRelation != null) {
                boolean result = this.removeById(id);
                if (result) {
                    List<UserRoleCache> cacheList = userRoleCache.get(generateKey(frameUserRoleRelation));
                    if (cacheList == null) {
                        cacheList = new ArrayList<>();
                    }
                    cacheList.removeIf(cache -> cache.getId().equals(frameUserRoleRelation.getId()));
                    userRoleCache.put(generateKey(frameUserRoleRelation), cacheList);
                }
                return result;
            }
            return false;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public FrameUserRoleRelation find(Long id) {
        return this.getById(id);
    }

    @Override
    public List<FrameUserRoleRelation> findList(QueryWrapper<FrameUserRoleRelation> qw) {
        return this.list(qw);
    }

    @Override
    public List<FrameUserRoleRelation> findRoleListByUserId(Long userId) {
        List<UserRoleCache> userRoleCacheList = userRoleCache.get(userId);
        if (userRoleCacheList == null) {
            userRoleCacheList =new ArrayList<>();
        }
        return IUserRoleCacheMapper.INSTANCE.toEntityList(userRoleCacheList);
    }

    private Long generateKey(FrameUserRoleRelation frameUserRoleRelation) {
        return frameUserRoleRelation.getUser_id();
    }
}
